package com.study.tx.annotation;

import com.alibaba.druid.pool.DruidDataSource;
import com.study.tx.common.listener.*;
import com.study.tx.common.utils.ApplicationContextUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * Spring 事务配置类：数据源、事务管理器、启用事务注解支持等。
 * 注意：@EnableTransactionManagement 的功能就是启用注解事务管理，等同于 xml 配置中的 <tx:annotation-driven/>
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2022年08月25日
 */
@Configuration
@EnableTransactionManagement(proxyTargetClass = false)
@ComponentScan(value = {"com.study.tx.annotation.dao", "com.study.tx.annotation.service"})
@PropertySource(value = {"classpath:com/study/tx/jdbc.properties"}, ignoreResourceNotFound = true, encoding = "UTF-8")
public class AnnotationTxConfig {
    @Value("${db.driverClassName}")
    private String driverClassName;
    @Value("${db.url}")
    private String url;
    @Value("${db.username}")
    private String username;
    @Value("${db.password}")
    private String password;

    @Bean
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(this.dataSource());
        return transactionManager;
    }

    @Bean
    public TransactionTemplate transactionTemplate() {
        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(this.transactionManager());
        // 设置事务传播属性，默认值为 PROPAGATION_REQUIRED
        //transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 设置事务隔离级别，默认值为 ISOLATION_DEFAULT(使用底层数据库的默认隔离级别)
        //transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
        // 设置事务是否只读，默认值为 false
        //transactionTemplate.setReadOnly(false);
        // 设置事务超时时间，默认值为 -1(使用底层数据库的默认事务超时时间)
        //transactionTemplate.setTimeout(TransactionDefinition.TIMEOUT_DEFAULT);
        return transactionTemplate;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(this.dataSource());
        return jdbcTemplate;
    }

    @Bean
    public ApplicationContextUtils applicationContextUtils() {
        ApplicationContextUtils applicationContextUtils = new ApplicationContextUtils();
        return applicationContextUtils;
    }

    @Bean
    public MyTransactionListener myTransactionListener() {
        MyTransactionListener myTransactionListener = new MyTransactionListener();
        return myTransactionListener;
    }

    @Bean
    public MyTransactionEventListener myTransactionEventListener() {
        MyTransactionEventListener myTransactionEventListener = new MyTransactionEventListener();
        return myTransactionEventListener;
    }

    @Bean
    public MyOrderTransactionEventListener myOrderTransactionEventListener() {
        MyOrderTransactionEventListener myOrderTransactionEventListener = new MyOrderTransactionEventListener();
        return myOrderTransactionEventListener;
    }

    @Bean
    public MyOrderItemTransactionEventListener myOrderItemTransactionEventListener() {
        MyOrderItemTransactionEventListener myOrderItemTransactionEventListener = new MyOrderItemTransactionEventListener();
        return myOrderItemTransactionEventListener;
    }
}
